import { ControlVOBase, deepCopy } from '@/core';
import {
	EditFormActionType,
	ICtrlActionResult,
	IEditFormAbility,
	IParam,
	IWizardPanelAbility,
	IWizardPanelController,
	IWizardPanelControllerParams,
	IWizardPanelModel,
	IWizardPanelStore,
	WizardPanelActionType,
} from '@/core/interface';
import WizardPanelService from '@/core/modules/ctrl-service/wizard-panel-service';
import { DECtrlController } from './de-ctrl-controller';

/**
 * 向导面板部件控制器
 *
 * @export
 * @class WizardPanelController
 * @extends {DECtrlController<WizardPanelActionType, IWizardPanelStore, IWizardPanelAbility>}
 * @implements {IWizardPanelController<IWizardPanelStore, IWizardPanelAbility>}
 */
export class WizardPanelController
	extends DECtrlController<
		WizardPanelActionType,
		IWizardPanelStore,
		IWizardPanelAbility
	>
	implements IWizardPanelController<IWizardPanelStore, IWizardPanelAbility>
{
	/**
	 * 向导面板模型
	 *
	 * @type {IWizardPanelModel}
	 * @memberof WizardPanelController
	 */
	protected declare model: IWizardPanelModel;

	/**
	 * 部件服务
	 *
	 * @type {FormService<ControlVOBase>}
	 * @memberof FormController
	 */
	declare ctrlService: WizardPanelService<ControlVOBase>;

	/**
	 * Creates an instance of WizardPanelController.
	 * @param {IWizardPanelControllerParams<WizardPanelActionType, IWizardPanelAbility>} params
	 * @memberof WizardPanelController
	 */
	public constructor(
		params: IWizardPanelControllerParams<
			WizardPanelActionType,
			IWizardPanelAbility
		>
	) {
		super(params);
		this.ctrlInit(params);
	}

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param {IDrtabControllerParams<DrtabActionType, IDrtabAbility>} params
	 * @memberof DrtabController
	 */
	protected processCtrlInit(
		params: IWizardPanelControllerParams<
			WizardPanelActionType,
			IWizardPanelAbility
		>
	) {
		super.processCtrlInit(params);
		const model = this.getModel<IWizardPanelModel>();
		const firstForm = model.wizardForm.find((form: IParam) => form.firstForm);
		let firstFormTag = '';
		if (firstForm) {
			firstFormTag = firstForm.formTag;
		}
		Object.assign(this.store, {
			formParam: {},
			activeForm: {},
			firstFormTag: firstFormTag,
			historyForms: [],
			curState: '',
		});
	}

	/**
	 * @description 部件挂载
	 * @memberof WizardPanelController
	 */
	public ctrlMounted(): void {
		super.ctrlMounted();
		this.formLoad();
	}

	/**
	 * 加载数据
	 *
	 * @param {IParam} [opts={}]
	 * @return {*}  {Promise<ICtrlActionResult>}
	 * @memberof WizardPanelController
	 */
	async load(opts: IParam = {}): Promise<ICtrlActionResult> {
		const { context, viewParams } = this.store;
		const tempContext = deepCopy(context);
		const arg: any = { ...opts };
		Object.assign(arg, viewParams);
		this.beforeAsyncAction('load', tempContext, arg);
		// todo 后台问题、临时添加
		this.computedActiveForm();
		this.formLoad();
		try {
			const response: any = await this.ctrlService.init(
				this.model.initAction,
				tempContext,
				arg
			);
			if (response && response.status === 200) {
				this.store.formParam = response.data;
				const entityCodeName = this.model.entityCodeName.toLowerCase();
				if (response.data[entityCodeName]) {
					Object.assign(this.store.context, {
						[entityCodeName]: response.data[entityCodeName],
					});
				}
				this.computedActiveForm();
				this.formLoad();
				this.afterAsyncAction('load', response);
				return { ok: true, data: [this.store.formParam], rowData: response };
			}
			this.afterAsyncAction('load', response);
			return { ok: false, data: [this.store.formParam], rowData: response };
		} catch (error: any) {
			this.afterAsyncAction('load', error);
			return { ok: false, data: [this.store.formParam], rowData: error };
		}
	}

	/**
	 * @description 计算激活表单
	 * @memberof WizardPanelController
	 */
	computedActiveForm() {
		let activeFormTag = '';
		if (this.model.stateField && this.store.formParam[this.model.stateField]) {
			const stepTag = this.store.formParam[this.model.stateField];
			if (Object.keys(this.model.steps).length > 0) {
				this.model.steps.forEach((step: IParam) => {
					if (step.stepTag === stepTag) {
						activeFormTag = step.stepTag;
					}
				});
			}
			if (!activeFormTag) {
				activeFormTag = this.store.firstFormTag;
			}
		} else {
			activeFormTag = this.store.firstFormTag;
		}
		if (activeFormTag) {
			const form = this.model.editForm.find((form: IParam) =>
				Object.is(form.name, `${this.model.name}_form_${activeFormTag}`)
			);
			if (form) {
				this.store.activeForm = form;
				this.store.historyForms.push(form);
			}
		}
	}

	/**
	 * @description 表单加载
	 * @memberof WizardPanelController
	 */
	public formLoad() {
		if (this.store.activeForm) {
			const form = this.getSubAbility<IEditFormAbility>(
				this.store.activeForm.name
			);
			if (form) {
				form.panelAction(
					this.store.activeForm.actions.loadAction,
					'load',
					this.store.formParam
				);
			}
		}
	}

	/**
	 * @description 上一步
	 * @return {*}
	 * @memberof WizardPanelController
	 */
	public async prevStep() {
		const length = this.store.historyForms.length;
		if (length > 1) {
			this.store.curState = 'PREV';
			if (this.store.activeForm.actions.preAction) {
				const form = this.getSubAbility<IEditFormAbility>(
					this.store.activeForm.name
				);
				if (form) {
					form.panelAction(
						this.store.activeForm.actions.preAction,
						'save',
						this.store.formParam
					);
				}
			} else {
				this.store.activeForm = this.store.historyForms[length - 1];
				setTimeout(() => {
					this.formLoad();
				}, 1);
				this.store.historyForms.splice(length - 1, 1);
			}
		}
	}

	/**
	 * @description 下一步
	 * @return {*}
	 * @memberof WizardPanelController
	 */
	public async nextStep() {
		if (this.store.activeForm) {
			const form = this.getSubAbility<IEditFormAbility>(
				this.store.activeForm.name
			);
			if (form) {
				if (
					(await form.formValidate()) &&
					this.store.activeForm.actions.saveAction
				) {
					this.store.curState = 'NEXT';
					form.panelAction(
						this.store.activeForm.actions.saveAction,
						'save',
						this.store.formParam
					);
				} else {
					App.getNotificationHelper().error(
						App.ts('app.error.rulesexception', '值规则校验异常')
					);
				}
			}
		}
	}

	/**
	 * @description 完成
	 * @memberof WizardPanelController
	 */
	public async finish() {
		if (this.store.activeForm) {
			const form = this.getSubAbility<IEditFormAbility>(
				this.store.activeForm.name
			);
			if (form) {
				if (
					(await form.formValidate()) &&
					this.store.activeForm.actions.saveAction
				) {
					this.store.curState = 'FINISH';
					await form.panelAction(
						this.store.activeForm.actions.saveAction,
						'save',
						this.store.formParam
					);
					App.getNotificationHelper().success(
						App.ts('app.success.finishedaction', '操作完成')
					);
					this.emit('closeView', [this.store.formParam]);
				} else {
					App.getNotificationHelper().error(
						App.ts('app.error.rulesexception', '值规则校验异常')
					);
				}
			}
		}
	}

	/**
	 * @description 获取下一步表单
	 * @memberof WizardPanelController
	 */
	public getNextForm(): IParam | undefined {
		if (this.store.formParam && this.store.formParam['srfnextform']) {
			return this.model.editForm.find((item: IParam) =>
				Object.is(
					item.name,
					`${this.model.name}_form_${this.store.formParam[
						'srfnextform'
					].toLowerCase()}`
				)
			);
		} else {
			let index = this.model.editForm.findIndex((item: IParam) =>
				Object.is(item.name, this.store.activeForm.name)
			);
			if (index >= 0) {
				if (this.model.editForm[index + 1]) {
					return this.model.editForm[index + 1];
				}
			}
		}
	}

	/**
	 * @description 处理点击
	 * @param {string} value
	 * @memberof WizardPanelController
	 */
	public handleItemClick(value: string) {
		switch (value) {
			case 'prev':
				this.prevStep();
				break;
			case 'next':
				this.nextStep();
				break;
			case 'finish':
				this.finish();
				break;
		}
	}

	/**
	 * @description 处理部件行为
	 * @param {string} name
	 * @param {EditFormActionType} action
	 * @param {IParam[]} data
	 * @memberof WizardPanelController
	 */
	public handleCtrlAction(
		name: string,
		action: EditFormActionType,
		data: IParam[]
	): void {
		super.handleCtrlAction(name, action, data);
		if (Object.is(action, 'save')) {
			this.handleFormSave(name, data);
		} else if (Object.is(action, 'load')) {
			this.handleFormLoad(name, data);
		}
	}

	/**
	 * @description 处理表单保存
	 * @param {string} name
	 * @param {IParam} data
	 * @memberof WizardPanelController
	 */
	public handleFormSave(name: string, data: IParam) {
		Object.assign(this.store.formParam, data);
		if (Object.is(this.store.curState, 'NEXT')) {
			const index = this.store.historyForms.findIndex((form: IParam) =>
				Object.is(form.name, name)
			);
			if (index === -1) {
				const form = this.model.editForm.find((item: IParam) =>
					Object.is(item.name, name)
				);
				if (form) {
					this.store.historyForms.push(form);
				}
			}
			const nextForm = this.getNextForm();
			if (nextForm) {
				this.store.activeForm = nextForm;
				setTimeout(() => {
					this.formLoad();
				}, 1);
			} else {
				this.handleFormFinish();
			}
		} else if (Object.is(this.store.curState, 'PREV')) {
			const length = this.store.historyForms.length;
			if (length > 1) {
				this.store.activeForm = this.store.historyForms[length - 1];
				setTimeout(() => {
					this.formLoad();
				}, 1);
				this.store.historyForms.splice(length - 1, 1);
			}
		} else if (Object.is(this.store.curState, 'FINISH')) {
			this.handleFormFinish();
		}
	}

	/**
	 * @description 处理表单加载
	 * @param {string} name
	 * @param {IParam} data
	 * @memberof WizardPanelController
	 */
	public handleFormLoad(name: string, data: IParam) {
		if (data) {
			Object.assign(this.store.formParam, data);
		}
	}

	/**
	 * @description 向导表单完成
	 * @return {*}
	 * @memberof WizardPanelController
	 */
	public async handleFormFinish() {
		const arg: any = {};
		Object.assign(arg, this.store.formParam);
		Object.assign(arg, { viewParams: this.store.viewParams });
		let tempContext: any = deepCopy(this.store.context);
		try {
			const response: any = await this.ctrlService.finish(
				this.model.finishAction,
				tempContext,
				arg
			);
			if (response && response.status === 200) {
				const data = response.data;
				this.emit('finish', data);
				return response;
			}
		} catch (response: any) {
			App.getNotificationHelper().error(
				App.ts('app.error.rulesexception', '值规则校验异常')
			);
			return response;
		}
	}

	/**
	 * 获取能力
	 *
	 * @return {*}  {IWizardPanelAbility}
	 * @memberof WizardPanelController
	 */
	getAbility(): IWizardPanelAbility {
		return {
			...super.getAbility(),
			load: this.load.bind(this),
		};
	}
}
